#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <vector>

// 解决粘包问题, 处理独立报文
#define SEP "X"
#define SEP_LEN strlen(SEP)

// 序列化和反序列化, 使用X作为分隔符
#define SPACE " "
#define SPACE_LEN strlen(SPACE)

// 把传进来的缓冲区进行切分 -> 切分成一个报文一个报文的类型
void SpeliteMessage(std::string& buffer, std::vector<std::string>* out)
{
    while (true)
    {
        auto pos = buffer.find(SEP);
        if (std::string::npos == pos) break;
        std::string message = buffer.substr(0, pos);
        buffer.erase(0, pos + SEP_LEN);
        out->push_back(message);
    }
}

std::string EnCode(std::string& s)
{
    return s + SEP;
}

class Request
{
public:
    std::string Serialize()
    {
        std::string str;
        str += std::to_string(_x);
        str += SPACE;
        str += _op;
        str += SPACE;
        str += std::to_string(_y);
        return str;
    } 

    bool Deserialize(const std::string& str)
    {
        std::size_t left = str.find(SPACE);
        if (left == std::string::npos)
            return false;
        std::size_t right = str.rfind(SPACE);
        if (right == std::string::npos)
            return false;
        _x = atoi(str.substr(0, left).c_str());
        _y = atoi(str.substr(right + SPACE_LEN).c_str());
        if (left + SPACE_LEN > str.size())  return false;
        _op = str[left + SPACE_LEN];
    }

    Request(int x, int y, int op)
        :_x(x)
        ,_y(y)
        ,_op(op)
    {}

    Request()   {}

    ~Request()  {}
public:
    int _x;
    int _y;
    char _op;
};

class Respense
{
public:
    std::string Serialize()
    {
        std::string s;
        s += std::to_string(_code);
        s += SPACE;
        s += std::to_string(_result);
        return s;
    }

    bool Deserialize(const std::string& str)
    {
        std::size_t pos = str.find(SPACE);
        if (pos == std::string::npos) return false;
        _code = atoi(str.substr(0, pos).c_str());
        _result = atoi(str.substr(pos + SPACE_LEN).c_str());
        return true;
    }
public:
    Respense()  {}

    Respense(int result, int code)
        :_result(result)
        ,_code(code)
    {}

    ~Respense() {}
public:
    int _result;
    int _code;
};
